package cz.spock.core.controller;

import java.io.IOException;
import java.util.logging.Logger;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

import cz.spock.core.entity.Account;
import cz.spock.core.entity.security.AccountSecurity;
import cz.spock.core.service.AccountService;
import cz.spock.exception.AuthenticationException;
import cz.spock.exception.JsonException;
import cz.spock.exception.ParameterNotFoundException;


/**
 * super class for other controller classes, provides common "helper" methods
 * 
 * controllers are supposed to retrieve http and ajax requests
 * as reaction should send json message or redirect to view/modelAndView
 * 
 * @author miso
 *
 */
@Controller
public class BaseController {
    
    @Autowired
    private AccountService userService;
    
    protected static final Logger log = Logger.getLogger(BaseController.class.getName());
    
    /**
     * this method sends json response to ajax based client
     * 
     * @param response
     * @param json
     */
    protected void sendJson(HttpServletResponse response, String json) {
        response.setContentType("text/plain");
        response.setHeader("Cache-Control", "no-cache");
        ServletOutputStream out;
        try {
            out = response.getOutputStream();
            out.print(json);
            out.close();
        } catch (IOException e) {
            throw new JsonException("JsonException: cannot send json", e);
        }
    }
    
    /**
     * returns loginId of current user
     * @return
     */
    protected String getCurrentLogin() {
        // get author from security context
        SecurityContext securityContext = SecurityContextHolder.getContext();
        AccountSecurity userDetails = (AccountSecurity) securityContext.getAuthentication().getPrincipal();
        return userDetails.getLogin();
    }
    
    /**
     * returns current user's account
     * @return
     */    
    protected Account getCurrentUser() {
        Account account = null;
        account = userService.findAccountByLogin(this.getCurrentLogin());
        if(account == null) {
            throw new AuthenticationException("Authentication error: User not found.");
        }
        return account;
    }
    
    /**
     * reads parameter and returns Key object
     * 
     * @param request
     * @param param
     * @return
     */
    protected Key readParamAsKey(HttpServletRequest request, String param) {
        String parameter = this.readParamAsString(request, param);
        if(parameter == null) return null;
        Key key = null;
        key = KeyFactory.stringToKey(parameter);
        return key;
    }
    
    /**
     * same as readParamAsString but accepts null 
     * 
     * @param request
     * @param param
     * @return
     */
    protected String readParamAsString(HttpServletRequest request, String param) {
        String parameter = null;
        parameter = request.getParameter(param);
        return parameter;  
    }
    
    /**
     * reads parameter and returns integer
     * 
     * @param request
     * @param param
     * @return
     */
    protected int readParamAsInt(HttpServletRequest request, String param) {
        String parameter = null;
        parameter = request.getParameter(param);        
        return Integer.parseInt(parameter);  
    }   
    
    /**
     * returns string value of given parameter or throws exception if parameter not found
     * 
     * @param request
     * @param param
     * @return
     */
    @Deprecated // controller should accept all values, validation on service layer
    protected String readParamAsStringNotNull(HttpServletRequest request, String param) {
        String parameter = null;
        parameter = request.getParameter(param);
        if(parameter == null) {
            throw new ParameterNotFoundException("Parameter " + param + " not found in request.");
        }        
        return parameter;        
    }

}
